#include "ui/CodeEditor.h"
#include <QPainter>
#include <QTextBlock>
#include <QScrollBar>

CodeEditor::CodeEditor(QWidget *parent)
    : QPlainTextEdit(parent)
{
    m_lineNumberArea = new LineNumberArea(this);
    m_highlighter = new SyntaxHighlighter(document());
    
    connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
    connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
    connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
    
    updateLineNumberAreaWidth(0);
    highlightCurrentLine();
    
    // 设置主题样式
    setCodeTheme("dark");

    // 设置制表符宽度
    QFontMetrics metrics(font());
    setTabStopDistance(4 * metrics.horizontalAdvance(' '));
}

int CodeEditor::lineNumberAreaWidth()
{
    int digits = 1;
    int max = qMax(1, blockCount());
    while (max >= 10) {
        max /= 10;
        ++digits;
    }
    
    int space = 10 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;
    return space;
}

void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
{
    setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}

void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
    if (dy)
        m_lineNumberArea->scroll(0, dy);
    else
        m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
    
    if (rect.contains(viewport()->rect()))
        updateLineNumberAreaWidth(0);
}

void CodeEditor::resizeEvent(QResizeEvent *e)
{
    QPlainTextEdit::resizeEvent(e);
    
    QRect cr = contentsRect();
    m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}

void CodeEditor::highlightCurrentLine()
{
    QList<QTextEdit::ExtraSelection> extraSelections;
    
    if (!isReadOnly()) {
        QTextEdit::ExtraSelection selection;
        
        QColor lineColor = QColor(37, 37, 38);
        
        selection.format.setBackground(lineColor);
        selection.format.setProperty(QTextFormat::FullWidthSelection, true);
        selection.cursor = textCursor();
        selection.cursor.clearSelection();
        extraSelections.append(selection);
    }
    
    setExtraSelections(extraSelections);
}

void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    QPainter painter(m_lineNumberArea);
    painter.fillRect(event->rect(), QColor(30, 30, 30));
    
    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top());
    int bottom = top + qRound(blockBoundingRect(block).height());
    
    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number = QString::number(blockNumber + 1);
            painter.setPen(QColor(133, 133, 133));
            painter.drawText(0, top, m_lineNumberArea->width() - 5, fontMetrics().height(),
                           Qt::AlignRight, number);
        }
        
        block = block.next();
        top = bottom;
        bottom = top + qRound(blockBoundingRect(block).height());
        ++blockNumber;
    }
}

void CodeEditor::setLanguage(const QString &language)
{
    m_currentLanguage = language;
    m_highlighter->setLanguage(language);
}

void CodeEditor::setCodeTheme(const QString &theme)
{
    if (theme == "dark") {
        setStyleSheet(
            "QPlainTextEdit {"
            "    background-color: #1e1e1e;"
            "    color: #d4d4d4;"
            "    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;"
            "    font-size: 12px;"
            "    border: 1px solid #3e3e42;"
            "    border-radius: 4px;"
            "    padding-left: 5px;"
            "    selection-background-color: #264f78;"
            "}"
        );
    } else if (theme == "light") {
        setStyleSheet(
            "QPlainTextEdit {"
            "    background-color: #ffffff;"
            "    color: #000000;"
            "    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;"
            "    font-size: 12px;"
            "    border: 1px solid #d3d3d3;"
            "    border-radius: 4px;"
            "    padding-left: 5px;"
            "    selection-background-color: #add6ff;"
            "}"
        );
    }
}

// SyntaxHighlighter 实现

SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    // 设置默认格式
    m_keywordFormat.setForeground(QColor(86, 156, 214));  // 蓝色
    m_keywordFormat.setFontWeight(QFont::Bold);
    
    m_classFormat.setForeground(QColor(78, 201, 176));  // 青色
    
    m_singleLineCommentFormat.setForeground(QColor(106, 153, 85));  // 绿色
    m_singleLineCommentFormat.setFontItalic(true);
    
    m_multiLineCommentFormat.setForeground(QColor(106, 153, 85));
    m_multiLineCommentFormat.setFontItalic(true);
    
    m_quotationFormat.setForeground(QColor(206, 145, 120));  // 橙色
    
    m_functionFormat.setForeground(QColor(220, 220, 170));  // 黄色
    
    m_numberFormat.setForeground(QColor(181, 206, 168));  // 浅绿色
    
    m_preprocessorFormat.setForeground(QColor(155, 155, 155));  // 灰色
}

void SyntaxHighlighter::setLanguage(const QString &language)
{
    m_highlightingRules.clear();
    
    if (language == "cpp" || language == "c" || language == "cc" || 
        language == "cxx" || language == "h" || language == "hpp") {
        setupCppHighlighting();
    } else if (language == "m" || language == "mm") {
        setupObjectiveCHighlighting();
    } else if (language == "swift") {
        setupSwiftHighlighting();
    } else if (language == "java" || language == "kt") {
        setupJavaHighlighting();
    } else if (language == "py") {
        setupPythonHighlighting();
    } else if (language == "js" || language == "ts" || language == "jsx" || language == "tsx") {
        setupJavaScriptHighlighting();
    }
    
    rehighlight();
}

void SyntaxHighlighter::highlightBlock(const QString &text)
{
    // 应用所有高亮规则
    foreach (const HighlightingRule &rule, m_highlightingRules) {
        QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
        while (matchIterator.hasNext()) {
            QRegularExpressionMatch match = matchIterator.next();
            setFormat(match.capturedStart(), match.capturedLength(), rule.format);
        }
    }
}

void SyntaxHighlighter::setupCppHighlighting()
{
    HighlightingRule rule;
    
    // 关键字
    QStringList keywordPatterns;
    keywordPatterns << "\\bclass\\b" << "\\bstruct\\b" << "\\benum\\b" << "\\bunion\\b"
                    << "\\bnamespace\\b" << "\\btemplate\\b" << "\\btypename\\b"
                    << "\\bpublic\\b" << "\\bprivate\\b" << "\\bprotected\\b"
                    << "\\bvirtual\\b" << "\\boverride\\b" << "\\bfinal\\b"
                    << "\\bconst\\b" << "\\bstatic\\b" << "\\bextern\\b" << "\\bmutable\\b"
                    << "\\bvoid\\b" << "\\bint\\b" << "\\bfloat\\b" << "\\bdouble\\b"
                    << "\\bbool\\b" << "\\bchar\\b" << "\\blong\\b" << "\\bshort\\b"
                    << "\\bunsigned\\b" << "\\bsigned\\b" << "\\bauto\\b"
                    << "\\breturn\\b" << "\\bif\\b" << "\\belse\\b" << "\\bfor\\b"
                    << "\\bwhile\\b" << "\\bdo\\b" << "\\bswitch\\b" << "\\bcase\\b"
                    << "\\bbreak\\b" << "\\bcontinue\\b" << "\\bgoto\\b"
                    << "\\btry\\b" << "\\bcatch\\b" << "\\bthrow\\b"
                    << "\\bnew\\b" << "\\bdelete\\b" << "\\bthis\\b"
                    << "\\btrue\\b" << "\\bfalse\\b" << "\\bnullptr\\b";
    
    foreach (const QString &pattern, keywordPatterns) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // 类名
    rule.pattern = QRegularExpression("\\b[A-Z][a-zA-Z0-9_]+\\b");
    rule.format = m_classFormat;
    m_highlightingRules.append(rule);
    
    // 函数
    rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()");
    rule.format = m_functionFormat;
    m_highlightingRules.append(rule);
    
    // 数字
    rule.pattern = QRegularExpression("\\b[0-9]+\\.?[0-9]*\\b");
    rule.format = m_numberFormat;
    m_highlightingRules.append(rule);
    
    // 预处理器
    rule.pattern = QRegularExpression("#[a-zA-Z]+\\b");
    rule.format = m_preprocessorFormat;
    m_highlightingRules.append(rule);
    
    // 字符串
    rule.pattern = QRegularExpression("\".*\"");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 单行注释
    rule.pattern = QRegularExpression("//[^\n]*");
    rule.format = m_singleLineCommentFormat;
    m_highlightingRules.append(rule);
}

void SyntaxHighlighter::setupObjectiveCHighlighting()
{
    setupCppHighlighting();  // 先加载C++的高亮
    
    HighlightingRule rule;
    
    // Objective-C 特有关键字
    QStringList objcKeywords;
    objcKeywords << "\\b@interface\\b" << "\\b@implementation\\b" << "\\b@protocol\\b"
                 << "\\b@property\\b" << "\\b@synthesize\\b" << "\\b@dynamic\\b"
                 << "\\b@class\\b" << "\\b@end\\b" << "\\b@selector\\b"
                 << "\\b@private\\b" << "\\b@public\\b" << "\\b@protected\\b"
                 << "\\bIBOutlet\\b" << "\\bIBAction\\b"
                 << "\\bYES\\b" << "\\bNO\\b" << "\\bnil\\b"
                 << "\\bself\\b" << "\\bsuper\\b" << "\\bid\\b";
    
    foreach (const QString &pattern, objcKeywords) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // NS前缀的类
    rule.pattern = QRegularExpression("\\bNS[A-Z][a-zA-Z0-9_]*\\b");
    rule.format = m_classFormat;
    m_highlightingRules.append(rule);
}

void SyntaxHighlighter::setupSwiftHighlighting()
{
    HighlightingRule rule;
    
    // Swift关键字
    QStringList swiftKeywords;
    swiftKeywords << "\\bclass\\b" << "\\bstruct\\b" << "\\benum\\b" << "\\bprotocol\\b"
                  << "\\bextension\\b" << "\\bfunc\\b" << "\\bvar\\b" << "\\blet\\b"
                  << "\\bif\\b" << "\\belse\\b" << "\\bfor\\b" << "\\bwhile\\b"
                  << "\\bswitch\\b" << "\\bcase\\b" << "\\breturn\\b" << "\\bimport\\b"
                  << "\\bpublic\\b" << "\\bprivate\\b" << "\\binternal\\b" << "\\bfileprivate\\b"
                  << "\\bstatic\\b" << "\\bfinal\\b" << "\\boverride\\b" << "\\binit\\b"
                  << "\\bself\\b" << "\\bsuper\\b" << "\\btrue\\b" << "\\bfalse\\b" << "\\bnil\\b";
    
    foreach (const QString &pattern, swiftKeywords) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // 类型
    rule.pattern = QRegularExpression("\\b[A-Z][a-zA-Z0-9_]*\\b");
    rule.format = m_classFormat;
    m_highlightingRules.append(rule);
    
    // 函数
    rule.pattern = QRegularExpression("\\b[a-z][a-zA-Z0-9_]*(?=\\()");
    rule.format = m_functionFormat;
    m_highlightingRules.append(rule);
    
    // 数字
    rule.pattern = QRegularExpression("\\b[0-9]+\\.?[0-9]*\\b");
    rule.format = m_numberFormat;
    m_highlightingRules.append(rule);
    
    // 字符串
    rule.pattern = QRegularExpression("\".*\"");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 单行注释
    rule.pattern = QRegularExpression("//[^\n]*");
    rule.format = m_singleLineCommentFormat;
    m_highlightingRules.append(rule);
    
}

void SyntaxHighlighter::setupJavaHighlighting()
{
    HighlightingRule rule;
    
    // Java关键字
    QStringList javaKeywords;
    javaKeywords << "\\bclass\\b" << "\\binterface\\b" << "\\benum\\b" << "\\bextends\\b"
                 << "\\bimplements\\b" << "\\bpublic\\b" << "\\bprivate\\b" << "\\bprotected\\b"
                 << "\\bstatic\\b" << "\\bfinal\\b" << "\\babstract\\b" << "\\bnative\\b"
                 << "\\bvoid\\b" << "\\bint\\b" << "\\bfloat\\b" << "\\bdouble\\b"
                 << "\\bboolean\\b" << "\\bchar\\b" << "\\bbyte\\b" << "\\bshort\\b" << "\\blong\\b"
                 << "\\breturn\\b" << "\\bif\\b" << "\\belse\\b" << "\\bfor\\b"
                 << "\\bwhile\\b" << "\\bdo\\b" << "\\bswitch\\b" << "\\bcase\\b"
                 << "\\bbreak\\b" << "\\bcontinue\\b" << "\\btry\\b" << "\\bcatch\\b"
                 << "\\bfinally\\b" << "\\bthrow\\b" << "\\bthrows\\b"
                 << "\\bnew\\b" << "\\bthis\\b" << "\\bsuper\\b"
                 << "\\btrue\\b" << "\\bfalse\\b" << "\\bnull\\b"
                 << "\\bpackage\\b" << "\\bimport\\b";
    
    foreach (const QString &pattern, javaKeywords) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // 类名
    rule.pattern = QRegularExpression("\\b[A-Z][a-zA-Z0-9_]*\\b");
    rule.format = m_classFormat;
    m_highlightingRules.append(rule);
    
    // 注解
    rule.pattern = QRegularExpression("@[A-Za-z]+\\b");
    rule.format = m_preprocessorFormat;
    m_highlightingRules.append(rule);
    
    // 函数
    rule.pattern = QRegularExpression("\\b[a-z][a-zA-Z0-9_]*(?=\\()");
    rule.format = m_functionFormat;
    m_highlightingRules.append(rule);
    
    // 数字
    rule.pattern = QRegularExpression("\\b[0-9]+\\.?[0-9]*[fFlLdD]?\\b");
    rule.format = m_numberFormat;
    m_highlightingRules.append(rule);
    
    // 字符串
    rule.pattern = QRegularExpression("\".*\"");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 单行注释
    rule.pattern = QRegularExpression("//[^\n]*");
    rule.format = m_singleLineCommentFormat;
    m_highlightingRules.append(rule);
 
}

void SyntaxHighlighter::setupPythonHighlighting()
{
    HighlightingRule rule;
    
    // Python关键字
    QStringList pythonKeywords;
    pythonKeywords << "\\bclass\\b" << "\\bdef\\b" << "\\blambda\\b"
                   << "\\bif\\b" << "\\belif\\b" << "\\belse\\b"
                   << "\\bfor\\b" << "\\bwhile\\b" << "\\bbreak\\b" << "\\bcontinue\\b"
                   << "\\breturn\\b" << "\\byield\\b" << "\\bpass\\b"
                   << "\\btry\\b" << "\\bexcept\\b" << "\\bfinally\\b" << "\\braise\\b"
                   << "\\bimport\\b" << "\\bfrom\\b" << "\\bas\\b"
                   << "\\bwith\\b" << "\\bassert\\b"
                   << "\\bglobal\\b" << "\\bnonlocal\\b"
                   << "\\bTrue\\b" << "\\bFalse\\b" << "\\bNone\\b"
                   << "\\band\\b" << "\\bor\\b" << "\\bnot\\b" << "\\bin\\b" << "\\bis\\b";
    
    foreach (const QString &pattern, pythonKeywords) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // 装饰器
    rule.pattern = QRegularExpression("@[A-Za-z_][A-Za-z0-9_]*");
    rule.format = m_preprocessorFormat;
    m_highlightingRules.append(rule);
    
    // 函数和类
    rule.pattern = QRegularExpression("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
    rule.format = m_functionFormat;
    m_highlightingRules.append(rule);
    
    // 数字
    rule.pattern = QRegularExpression("\\b[0-9]+\\.?[0-9]*\\b");
    rule.format = m_numberFormat;
    m_highlightingRules.append(rule);
    
    // 字符串（单引号和双引号）
    rule.pattern = QRegularExpression("\".*\"|'.*'");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 三引号字符串
    rule.pattern = QRegularExpression("\"\"\".*\"\"\"|'''.*'''");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 注释
    rule.pattern = QRegularExpression("#[^\n]*");
    rule.format = m_singleLineCommentFormat;
    m_highlightingRules.append(rule);
}

void SyntaxHighlighter::setupJavaScriptHighlighting()
{
    HighlightingRule rule;
    
    // JavaScript关键字
    QStringList jsKeywords;
    jsKeywords << "\\bclass\\b" << "\\bfunction\\b" << "\\bconst\\b" << "\\blet\\b" << "\\bvar\\b"
               << "\\bif\\b" << "\\belse\\b" << "\\bfor\\b" << "\\bwhile\\b" << "\\bdo\\b"
               << "\\bswitch\\b" << "\\bcase\\b" << "\\bbreak\\b" << "\\bcontinue\\b"
               << "\\breturn\\b" << "\\btry\\b" << "\\bcatch\\b" << "\\bfinally\\b" << "\\bthrow\\b"
               << "\\bnew\\b" << "\\bthis\\b" << "\\bsuper\\b" << "\\bextends\\b"
               << "\\bimport\\b" << "\\bexport\\b" << "\\bfrom\\b" << "\\bas\\b"
               << "\\basync\\b" << "\\bawait\\b" << "\\byield\\b"
               << "\\btrue\\b" << "\\bfalse\\b" << "\\bnull\\b" << "\\bundefined\\b"
               << "\\btypeof\\b" << "\\binstanceof\\b" << "\\bin\\b" << "\\bof\\b";
    
    foreach (const QString &pattern, jsKeywords) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = m_keywordFormat;
        m_highlightingRules.append(rule);
    }
    
    // 函数
    rule.pattern = QRegularExpression("\\b[a-zA-Z_$][a-zA-Z0-9_$]*(?=\\()");
    rule.format = m_functionFormat;
    m_highlightingRules.append(rule);
    
    // 数字
    rule.pattern = QRegularExpression("\\b[0-9]+\\.?[0-9]*\\b");
    rule.format = m_numberFormat;
    m_highlightingRules.append(rule);
    
    // 字符串（单引号、双引号和模板字符串）
    rule.pattern = QRegularExpression("\".*\"|'.*'|`.*`");
    rule.format = m_quotationFormat;
    m_highlightingRules.append(rule);
    
    // 单行注释
    rule.pattern = QRegularExpression("//[^\n]*");
    rule.format = m_singleLineCommentFormat;
    m_highlightingRules.append(rule);
    
}